#pragma once

#include "Date.hpp"
#include "Time.hpp"

namespace header
{
namespace details
{

inline void get_now(int& year, int& month, int& day, int& hour, int& minute, int& second, int& microsecond)
{
    get_now_date(year, month, day);
    get_now_time(hour, minute, second, microsecond);
}

}   // namespace details

class DateTime
{
public:
    static void now(int& year, int& month, int& day, int& hour, int& minute, int& second, int& microsecond)
    {
        details::get_now(year, month, day, hour, minute, second, microsecond);
    }

public:
    DateTime();
    DateTime(const Date& date, const Time& time);
    DateTime(int year, int month, int day, int h, int m, int s = 0, int ms = 0);
    ~DateTime() = default;

public:
    std::string to_string(const std::string& format = "YYYY-MM-DD hh:mm:ss.z");

private:
    Date _date;
    Time _time;
};

DateTime::DateTime() { }

DateTime::DateTime(const Date& date, const Time& time)
    :_date{ date }, _time{ time }
{ }

DateTime::DateTime(int year, int month, int day, int h, int m, int s, int ms)
    :_date{ year, month, day }, _time{ h, m, s, ms }
{ }

std::string DateTime::to_string(const std::string& format)
{
    int index = 0;
    auto len = format.size();
    std::string res;
    int year  = _date.year();
    int month = _date.month();
    int day   = _date.day();
    int h     = _time.hour();
    int m     = _time.minute();
    int s     = _time.second();
    int ms    = _time.microsecond();
    for (; index < len; ++index) {
        if (format[index] == details::YearFormat) details::parse_year_format(index, format, year, res);
        else if (format[index] == details::MonthFormat) details::parse_month_format(index, format, month, res);
        else if (format[index] == details::DayFormat) details::parse_day_format(index, format, year, month, day, res);
        else if (format[index] == details::HourFormat) details::parse_hour_format(index, format, h, res);
        else if (format[index] == details::MinuteFormat) details::parse_minute_format(index, format, m, res);
        else if (format[index] == details::SecondFormat) details::parse_second_format(index, format, s, res);
        else if (format[index] == details::MicroSecondFormat) details::parse_microsecond_format(index, format, ms, res);
        else res.push_back(format[index]);
    }
    return res;
}

}   // namespace header
